package org.springframework.boot.netty.support;

import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;

import org.springframework.core.Conventions;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;


public class Model extends LinkedHashMap<String, Object> {

	/**
	 * Construct a new, empty {@code ModelMap}.
	 */
	public Model() {
	}


	public Model(String attributeName, @Nullable Object attributeValue)
	{
		addAttribute(attributeName, attributeValue);
	}


	public Model(Object attributeValue) {

		addAttribute(attributeValue);
	}



	public Model addAttribute(String attributeName, @Nullable Object attributeValue) {

		Assert.notNull(attributeName, "Model attribute name must not be null");
		put(attributeName, attributeValue);
		return this;
	}


	public Model addAttribute(Object attributeValue) {
		Assert.notNull(attributeValue, "Model object must not be null");
		if (attributeValue instanceof Collection && ((Collection<?>) attributeValue).isEmpty()) {
			return this;
		}
		return addAttribute(Conventions.getVariableName(attributeValue), attributeValue);
	}


	public Model addAllAttributes(@Nullable Collection<?> attributeValues) {
		if (attributeValues != null) {
			for (Object attributeValue : attributeValues) {
				addAttribute(attributeValue);
			}
		}
		return this;
	}


	public Model addAllAttributes(@Nullable Map<String, ?> attributes) {
		if (attributes != null) {
			putAll(attributes);
		}
		return this;
	}


	public Model mergeAttributes(@Nullable Map<String, ?> attributes) {
		if (attributes != null) {
			attributes.forEach((key, value) -> {
				if (!containsKey(key)) {
					put(key, value);
				}
			});
		}
		return this;
	}


	public boolean containsAttribute(String attributeName) {
		return containsKey(attributeName);
	}


	@Nullable
	public Object getAttribute(String attributeName) {
		return get(attributeName);
	}

}
